/*
 * Copyright 2007-2009 Perttu "celeron55" Ahola <celeron55@gmail.com>
 *
 * This file is part of jukumagic.
 *
 * jukumagic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jukumagic is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with jukumagic.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "common.h"
#include "objectcontainer.h"
#include "jukuapp.h"

#include <iostream>
#include <algorithm>

ObjectContainer::ObjectContainer()
{
	m_ignore_changes = false;
}

ObjectContainer::~ObjectContainer()
{
	m_owner = NULL;
	Clear();
}

void ObjectContainer::WriteBaseXML(TiXmlElement *element)
{
	if(element == NULL) return;
	for(std::list<JukuObject*>::iterator i = m_objects.begin(); i != m_objects.end(); i++){
		(*i)->WriteXML(element);
	}
	JukuObject::WriteBaseXML(element);
}

void ObjectContainer::ReadBaseXML(TiXmlElement *element)
{
	//std::cout<<"ObjectContainer::ReadBaseXML()"<<std::endl;
	if(element == NULL) return;
	m_ignore_changes = true;
	for(TiXmlElement *e = TiXmlHandle(element).FirstChildElement().Element(); e; e = e->NextSiblingElement())
	{
		JukuObject *object = wxGetApp().ReadXMLElement(e);
		if(object){
			/*std::cout<<"ObjectContainer: object is "
					<<wxString(object->GetTypeString()).mb_str(wxConvUTF8)<<std::endl;*/
			Add(object, NULL);
		}
		else{
			std::cout<<"ObjectContainer: wxGetApp().ReadXMLElement(e) == NULL"<<std::endl;
		}
	}
	JukuObject::ReadBaseXML(element);
	m_ignore_changes = false;
	ReportChange(OBJECT_CHANGE_CONTENTS);
}

void ObjectContainer::ChildChanged(ObjectChangeType type, JukuObject *obj)
{
	if(m_ignore_changes) return;

	if(type == OBJECT_CHANGE_SELECTION){
		if(obj->GetSelected() == true){
			m_selected_objects.insert(obj);
		}
		else{
			m_selected_objects.erase(obj);
		}
	}
	else if(type == OBJECT_CHANGE_CONTENTS){
	}
}

void ObjectContainer::SelfChanged(ObjectChangeType type)
{
	if(m_ignore_changes) return;

	if(type == OBJECT_CHANGE_SELECTION){
	}
	else if(type == OBJECT_CHANGE_CONTENTS){
	}
}

void ObjectContainer::Clear()
{
	m_ignore_changes = true;
	for(std::list<JukuObject*>::iterator i = m_objects.begin(); i != m_objects.end(); i++){
		(*i)->m_owner = NULL;
		delete *i;
	}
	m_objects.clear();
	m_ignore_changes = false;
	m_selected_objects.clear();
	ReportChange(OBJECT_CHANGE_CONTENTS);
}


void ObjectContainer::Clear(std::set<JukuObject*> &objects)
{
	for(std::list<JukuObject*>::iterator i = m_objects.begin(); i != m_objects.end(); ){
		std::set<JukuObject*>::iterator j = find(objects.begin(), objects.end(), (*i));
		if(j != objects.end()){
			if((*i)->GetSelected() == true){
				m_selected_objects.erase(*i);
			}
			(*i)->m_owner = NULL;
			delete *i;
			i = m_objects.erase(i);
		}
		else i++;
	}
}

const std::list<JukuObject*> & ObjectContainer::GetObjects()
{
	return m_objects;
}

bool ObjectContainer::Add(JukuObject* object, JukuObject *prev_object)
{
	if(object==NULL) return false;

	if(object->GetSelected() == true){
		m_selected_objects.insert(object);
	}

	if(m_objects.empty() || prev_object == NULL){
		m_objects.push_back(object);
	}
	else{
		std::list<JukuObject*>::iterator i;
		for(i = m_objects.begin(); i != m_objects.end(); i++) if(*i == prev_object) break;
		m_objects.insert(i, object);
	}
	
	// This sets the owner and reports change
	JukuObject::Add(object, prev_object);

	return true;
}

void ObjectContainer::SetSelected(bool selected)
{
	m_ignore_changes = true;
	std::list<JukuObject*>::iterator i;
	m_selected_objects.clear();
	if(selected){
		for(i = m_objects.begin(); i != m_objects.end(); i++){
			(*i)->SetSelected(true);
			m_selected_objects.insert((*i));
		}
	}
	else{
		for(i = m_objects.begin(); i != m_objects.end(); i++){
			(*i)->SetSelected(false);
		}
	}
	JukuObject::SetSelected(selected);
	m_ignore_changes = false;
	ReportChange(OBJECT_CHANGE_SELECTION);
}

const std::set<JukuObject*> & ObjectContainer::GetSelectedObjects()
{
	return m_selected_objects;
}

void ObjectContainer::SelectChildren(const std::set<JukuObject*> & objects)
{
	m_ignore_changes = true;
	for(std::set<JukuObject*>::const_iterator i = objects.begin(); i != objects.end(); i++){
		if((*i)->GetSelected() == false){
			(*i)->SetSelected(true);
			m_selected_objects.insert((*i));
		}
	}
	m_ignore_changes = false;
	ReportChange(OBJECT_CHANGE_SELECTION);
}

void ObjectContainer::MoveChildren(const std::set<JukuObject*> & objects, int dx, int dy)
{
	m_ignore_changes = true;
	for(std::set<JukuObject*>::const_iterator i = objects.begin(); i != objects.end(); i++){
		(*i)->Move(dx, dy);
	}
	m_ignore_changes = false;
	ReportChange(OBJECT_CHANGE_CONTENTS);
}

void ObjectContainer::DeleteSelectedObjects()
{
	if(m_selected_objects.empty()) return;
	Clear(m_selected_objects);
	ReportChange(OBJECT_CHANGE_CONTENTS);
}

void ObjectContainer::operator = (ObjectContainer &c)
{
	//std::cout<<"blö"<<std::endl;
	Clear();
	for(std::list<JukuObject*>::iterator i = c.m_objects.begin(); i != c.m_objects.end(); i++){
		JukuObject *o = (*i)->MakeACopy();
		Add(o, NULL);
	}
}

